<ng-template #labelTemplate>
  <!--
    MDC recommends that the text-field is a `<label>` element. This rather complicates the
    setup because it would require every form-field control to explicitly set `aria-labelledby`.
    This is because the `<label>` itself contains more than the actual label (e.g. prefix, suffix
    or other projected content), and screen readers could potentially read out undesired content.
    Excluding elements from being printed out requires them to be marked with `aria-hidden`, or
    the form control is set to a scoped element for the label (using `aria-labelledby`). Both of
    these options seem to complicate the setup because we know exactly what content is rendered
    as part of the label, and we don't want to spend resources on walking through projected content
    to set `aria-hidden`. Nor do we want to set `aria-labelledby` on every form control if we could
    simply link the label to the control using the label `for` attribute.

    *Note*: We add aria-owns as a workaround for an issue in JAWS & NVDA where the label isn't
    read if it comes before the control in the DOM.
  -->
  <label matFormFieldFloatingLabel
         [floating]="_shouldLabelFloat()"
         [required]="!hideRequiredMarker && _control.required"
         *ngIf="_hasFloatingLabel()"
         (cdkObserveContent)="_refreshOutlineNotchWidth()"
         [cdkObserveContentDisabled]="!_hasOutline()"
         [id]="_labelId"
         [attr.for]="_control.id"
         [attr.aria-owns]="_control.id">
    <ng-content select="mat-label"></ng-content>
  </label>
</ng-template>

<div class="mat-mdc-text-field-wrapper mdc-text-field" #textField
     [class.mdc-text-field--filled]="!_hasOutline()"
     [class.mdc-text-field--outlined]="_hasOutline()"
     [class.mdc-text-field--no-label]="!_hasFloatingLabel()"
     [class.mdc-text-field--disabled]="_control.disabled"
     [class.mdc-text-field--invalid]="_control.errorState"
     (click)="_control.onContainerClick && _control.onContainerClick($event)">
  <div class="mat-mdc-form-field-focus-overlay" *ngIf="!_hasOutline() && !_control.disabled"></div>
  <div class="mat-mdc-form-field-flex">
    <div *ngIf="_hasOutline()" matFormFieldNotchedOutline
         [matFormFieldNotchedOutlineOpen]="_shouldLabelFloat()"
         [matFormFieldNotchedOutlineWidth]="_outlineNotchWidth">
      <ng-template [ngIf]="!_forceDisplayInfixLabel()">
        <ng-template [ngTemplateOutlet]="labelTemplate"></ng-template>
      </ng-template>
    </div>

    <div class="mat-mdc-form-field-prefix" *ngIf="_prefixChildren.length" #prefixContainer>
      <ng-content select="[matPrefix]"></ng-content>
    </div>

    <div class="mat-mdc-form-field-infix">
      <ng-template [ngIf]="!_hasOutline() || _forceDisplayInfixLabel()">
        <ng-template [ngTemplateOutlet]="labelTemplate"></ng-template>
      </ng-template>

      <ng-content></ng-content>
    </div>

    <div class="mat-mdc-form-field-suffix" *ngIf="_suffixChildren.length">
      <ng-content select="[matSuffix]"></ng-content>
    </div>
  </div>

  <div matFormFieldLineRipple *ngIf="!_hasOutline()"></div>
</div>

<div class="mat-mdc-form-field-subscript-wrapper"
     [ngSwitch]="_getDisplayedMessages()">
  <div *ngSwitchCase="'error'" [@transitionMessages]="_subscriptAnimationState">
    <ng-content select="mat-error"></ng-content>
  </div>

  <div class="mat-mdc-form-field-hint-wrapper" *ngSwitchCase="'hint'"
       [@transitionMessages]="_subscriptAnimationState">
    <mat-hint *ngIf="hintLabel" [id]="_hintLabelId">{{hintLabel}}</mat-hint>
    <ng-content select="mat-hint:not([align='end'])"></ng-content>
    <div class="mat-mdc-form-field-hint-spacer"></div>
    <ng-content select="mat-hint[align='end']"></ng-content>
  </div>
</div>
